9 役に立つコードの抜粋


ここでは、読者のプログラムの中で使うことのできるちょっとした Flex 定義を一覧にして示します。これらの多くは、このマニュアルを読んだあとでは、かなり自明なはずです。しかし、読者がこうしたコードを最初から作らなくてもよいようにするために、ここに入れてあります。

9.1 コメントの処理

***ページの 4.1 節「Flex と C」において述べたように、コメントは input() を使って処理することができます。これをおこなうためのコードは以下のようになります。

これは Flex と Lex の両方で正当なコードです。コメントは排他的スタート状態を使って処理することも可能で、こちらの方がより美しく、より効率的です。スタート状態を使ってコメントを処理するコードは以下のようになります。 改行の1つ前までと改行とを別々に処理した方が良いのは、そうしないと内部のマッチ処理用のバッファをオーバーフローさせてしまうようなルールを作ることになってしまうからです。Lex は排他的スタート状態をサポートしていないので、このコードは Lex では動きません。この例は分かりやすいのですが、実際には単一文字をマッチするのに多くの時間を無駄に消費するため非効率です。もっと長いテキストにマッチするように変更することで、スピードをかなり向上させることができます。例えば、以下のように書き直すことができます。 これは、Flex と一緒に配布されている flexdoc.1 の中にある例とほとんど同一です。これはより長いテキスト・ブロックにマッチするためはるかに高速ですし、ルールの中で改行のみにマッチさせる必要もありません。

9.2 文字列リテラルの処理

文字列は、それが入力として与えられたとき破棄されないという点で、コメントとは若干異なります。しかし、基本的なアプローチは同じです。第1の方法としては、input() を使って文字列を処理することができます。そのコードは以下のようになります。

このスキャナは、複数行にわたる文字列や様々なエスケープ・シーケンスを処理します。また、文字列がどのような長さでも構わないように動的バッファを使っています。これと同じことをスタート状態を使っておこなうコードは以下のようになります。 このスキャナは string1.lex よりもモジュール化されていて、おそらくはより分かりやすいでしょう。エラーのルールは INITIAL 状態に戻るようになっていることに注意してください。こうしないと、スキャナは不当な文字列と正当な文字列とを結合してしまいます。ここでも、Flex のバッファ(YY_BUF_SIZE)が十分に大きいということをあてにせず、動的バッファを使いました。内部バッファが十分に大きいという確信が持てるのであれば、yytext だけを使うことも可能です。この場合には、yytext の右端が確実に最初の位置に留まるようにすることが重要です。より詳しい情報については***ページの 4.1 節「Flex と C」の yymore の項を参照してください。

9.3 数字の処理

ここでは、C に見られる様々な数値形式に対してよく使われる定義をいくつか示し、さらにその使い方の実例を1つ示します。注目すべき主要な点は、数の値を獲得するために scanf() を使っている点とオーバーフローが発生しないよう long 型の値をスキャンするデフォルトのルールです。一般的には、yytext を数に変換する最良の方法は sscanf() を使うことです。

16 進定数については変換する前に先頭の 0x をスキップする必要がある点に注意してください。これは sscanf() の仕様です。

9.4 複数のスキャナ

時には1つのプログラムの中で複数のスキャナを持つ必要がある場合がありますが、こうすると2回以上現れる関数や変数についてリンカが文句を言ってきます。スキャナとそれに関連するすべてのものの名前を変更する必要があります。すべてのスキャナ関数、マクロ、データの名前は yy もしくは YY で始まりますので、これはきわめて簡単です。しなければならないことは名前の接頭辞を変更することだけです。これは sed を使って簡単に行うことができますが、ここではおもしろ半分で、これをおこなう flex スキャナを示しましょう。

すべてのスキャナ関数の名前を変更するには、コマンドライン上で以下のように実行するだけです。 これにより好きなだけ多くのスキャナを含めることができるようになります。これとほとんど同じことを排他的スタート状態と複数のバッファを使って実現することも可能ですが、その方法は多少複雑になります。

注:いくつかの Flex 内部ルーチンは将来 Flex ライブラリ(-lfl)の中に移されるでしょう。そうなるとこのテクニックは機能しなくなります。しかし、この変更がおこなわれる時には、変更する必要のある関数名を変更する方法を Flex 自身がサポートするようになるでしょう。

9.5 その他


Copyright (C) 1992, 1993 Free Software Foundation

Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.

Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by the Free Software Foundation.


日本語訳:市川和久
Japanese translation by Kazuhisa Ichikawa (ki@home.email.ne.jp)